#include "../include/easylog.h"
#include <chrono>
#include <algorithm>

void bench(const std::string& name, size_t th_num, size_t msg_num, size_t msg_len)
{
    easylog::Logger::ptr logger = easylog::getLogger(name);
    printf("测试开始  日志条数: %ld, 单条大小: %ld Bytes, 总大小: %ld KB\n", 
    msg_num, msg_len, msg_num * msg_len / 1024);
    
    std::string msg(msg_len - 1, 'A');//日志消息
    size_t msg_num_per_th = msg_num / th_num;//平均单个线程输出日志条数
    std::vector<std::thread> threads;
    std::vector<double> costs(th_num);
    //多线程写日志
    for(int i = 0; i < th_num; ++i)
    {
        threads.emplace_back([&, i](){
            auto start = std::chrono::high_resolution_clock::now();//开始时间
            for(int j = 0; j < msg_num_per_th; ++j)//输出日志
                logger->debug(msg);
            auto end = std::chrono::high_resolution_clock::now();//结束时间
            std::chrono::duration<double> cost = end - start;//消耗时间
            costs[i] = cost.count();
            printf("线程%d: \t输出日志: %ld 条, 耗时 %lf s\n", i, msg_num_per_th, costs[i]);
        });
    }
    for(auto& th : threads)
        th.join();
    auto max_cost = *max_element(costs.begin(), costs.end());//多线程耗时最久的时间
    size_t msg_num_per_sec = msg_num / max_cost;//每秒输出日志数量
    size_t size_per_sec = msg_num * msg_len / max_cost / 1024;//每秒输出日志大小 KB
    printf("\t总耗时: %lf s\n", max_cost);
    printf("\t每秒输出日志条数: %ld 条\n", msg_num_per_sec);
    printf("\t每秒输出日志大小: %ld KB\n", size_per_sec);
}

void sync_bench()
{
    std::cout << "----------------------- 同步日志器性能测试 -----------------------\n";
    std::unique_ptr<easylog::LoggerBuilder> builder(new easylog::GlobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(easylog::LoggerType::LOGGER_SYNC);
    builder->buildSink<easylog::FileSink>("./logfile/sync.log");
    builder->build();
    bench("sync_logger", 4, 1000000, 100);
    std::cout << std::endl;
}

void async_bench()
{
    std::cout << "----------------------- 异步日志器性能测试 -----------------------\n";
    std::unique_ptr<easylog::LoggerBuilder> builder(new easylog::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildFormatter("[%f:%l]%m%n");
    builder->setUnsafeAsync();
    builder->buildLoggerType(easylog::LoggerType::LOGGER_ASYNC);
    //builder->buildSink<easylog::FileSink>("./logfile/async.log");
    builder->buildSink<easylog::RollBySizeSink>("./logfile/size/log-", 1024 * 10, 20);
    builder->build();
    bench("async_logger", 4, 100000, 100);
    std::cout << std::endl;
}

int main()
{
    //sync_bench();
    async_bench();
}